/********************************************************************
 * File: instrument.c
 *
 * Instrumentation source -- link this with your application, and
 *  then execute to build trace data file (trace.txt).
 *
 * Author: M. Tim Jones <mtj@mtjones.com>
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <dirent.h>
#include <string.h>
/* Function prototypes with attributes */
#ifdef _cplusplus
extern  "C"
{
#endif
	void main_constructor( void )
		__attribute__ ((no_instrument_function, constructor));

	void main_destructor( void )
		__attribute__ ((no_instrument_function, destructor));

	void __cyg_profile_func_enter( void *, void * ) 
		__attribute__ ((no_instrument_function));

	void __cyg_profile_func_exit( void *, void * )
		__attribute__ ((no_instrument_function));


	typedef  struct  LOCKS
	{
		int pfilend;
		int state;
		FILE *pfile;
	}_LOCKS;
	void   LockFileSelf(char *,_LOCKS *lockhnd)
		__attribute__((no_instrument_function));
	void   UnLockFileSelf(_LOCKS *lockhnd)
		__attribute__((no_instrument_function));

	void main_constructor( void )
	{
		FILE *pFile;
		struct stat  ustat;
		if (stat("trace.txt",&ustat) == -1)
		{
			pFile =   fopen("trace.txt","w");
			fclose(pFile);
		}

	}


	void main_deconstructor( void )
	{

	}


	void __cyg_profile_func_enter( void *thiss, void *callsite )
	{

		_LOCKS    lockfiles ;
		memset(&lockfiles,0,sizeof(_LOCKS));
		LockFileSelf("trace.txt",&lockfiles);
		if ( lockfiles.state != 0  )
		{
			UnLockFileSelf(&lockfiles);
			return ;

		}
		lockfiles.pfile  =  fopen("trace.txt","a");
		fprintf(lockfiles.pfile, "E%p\n", (int *)thiss);

		UnLockFileSelf(&lockfiles);


	}


	void __cyg_profile_func_exit( void *thiss, void *callsite )
	{

		_LOCKS    lockfiles ;

		memset(&lockfiles,0,sizeof(_LOCKS));
		LockFileSelf("trace.txt",&lockfiles);
		if ( lockfiles.state != 0  )
		{
			UnLockFileSelf(&lockfiles);
			return;

		 
		}
		lockfiles.pfile  =  fopen("trace.txt","a");
		fprintf(lockfiles.pfile, "X%p\n", (int *)thiss);

		UnLockFileSelf(&lockfiles);
	}
	void  LockFileSelf(char *fname,_LOCKS *lockhnd)
	{
		struct  flock  locks; 

		lockhnd->pfilend =  open(fname,O_RDWR );
		if (lockhnd->pfilend ==  -1)
		{
			lockhnd->state  = 1;
			return;
		}


		locks.l_type    = F_RDLCK;
		locks.l_whence  = SEEK_SET;
		locks.l_start   = 0;
		locks.l_len     = 0;
		if (fcntl(lockhnd->pfilend, F_SETLKW, &locks) ==  -1)
		{
			lockhnd->state  = 1;
		}
		


	}
	void UnLockFileSelf(_LOCKS *lockhnd)
	{

		struct flock lock;
		lock.l_type    = F_UNLCK;
		lock.l_whence  = SEEK_SET;
		lock.l_start   = 0;
		lock.l_len     = 0;
		fcntl(lockhnd->pfilend, F_SETLK, &lock);
		close(lockhnd->pfilend);
		if (lockhnd->pfile !=NULL)
		{
			fflush(lockhnd->pfile);
			fclose(lockhnd->pfile);
		}
	}
#ifdef _cplusplus
}
#endif
